# Carga de librerías necesarias
library(DiagrammeR)
library(ahp)
# Carga de funciones multicriterio
source("teoriadecision_funciones_multicriterio.R")
source("teoriadecision_funciones_multicriterio_diagram.R")
source("teoriadecision_funciones_multicriterio_utiles.R")
# Carga otras funciones
source("otras_funciones.R")
source("tablas_planteamiento_AHP.R")
source("animación_grafo.R")Adquisición de un monitor de PC mediante métodos multicriterio
Presentación del problema
El objetivo de este documento será elegir la mejor alternativa a la hora de adquirir un nuevo monitor de PC. Se va a considerar que el individuo interesado en esta adquisición va a ser un arquitecto que necesita un nuevo monitor para su estudio.
Se van a seleccionar 5 monitores diferentes, que tratan de representar una variedad de opciones en el mercado actual. Los criterios que se van a considerar son los siguientes:
- Precio (€)
- Tamaño (pulgadas)
- Frecuencia de actualización (Hz) o de refresco.
- Resolución (px)
- Consumo energético (W) en un instante.
- Densidad de píxeles (ppi)
- Brillo (nits)
- Contraste (en millones de colores M)
Y las alternativas las podemos ver en la siguiente tabla:
datos <- read.csv2("monitores.csv", header = FALSE, sep = ";")
colnames(datos) <- c("Modelo","Precio", "Tamaño", "Frecuencia", "Resolución", "Consumo", "Densidad", "Brillo", "Colores")
unidades <- c("€", "pulgadas", "Hz", "px", "W", "ppi", "nits", "M")
crea_tabla_estilo(datos, nombresfila = FALSE)| Modelo | Precio | Tamaño | Frecuencia | Resolución | Consumo | Densidad | Brillo | Colores |
|---|---|---|---|---|---|---|---|---|
| LG UltraFine 40WT95UF | 505 | 39.7 | 120 | 2160 | 40 | 139 | 450 | 1060 |
| Asus TUF Gaming VG27AQ3A | 244 | 27 | 180 | 1440 | 35 | 108 | 250 | 16.7 |
| MSI MAG401QR | 449 | 40 | 155 | 1440 | 39 | 93 | 400 | 1070 |
| Asus VZ27EHF | 108 | 27 | 100 | 1080 | 21 | 81 | 250 | 16.7 |
| Samsung UJ59 | 290 | 31.5 | 60 | 2160 | 37 | 139 | 270 | 1000 |
Este arquitecto busca un monitor que le permita trabajar con planos y renderizados de alta calidad. El precio le preocupa en poca medida, pero quiere un monitor que ofrezca buena resolución y una buena representación de colores. Además, valora un tamaño grande para facilitar su trabajo. En cuanto al consumo, quiere que sea lo más bajo posible, pero no lo valora especialmente.
Elegir un método
Planteamiento para el método AHP
Introducción
Para el método AHP, se va a dar una estructura jerárquica de criterios y subcriterios. Se van a considerar tres criterios: Coste, calidad de imagen y experiencia de usuario.
El criterio coste, incluye los subcriterios: precio y consumo energético.
El criterio calidad de imagen, incluye los subcriterios: resolución, densidad, brillo y colores.
El criterio experiencia de usuario, incluye los subcriterios: tamaño y frecuencia de actualización.
Vemos a continuación un diagrama que representa esta jerarquía:
DiagrammeR::grViz("
digraph {
node [shape = rectangle, style = 'rounded,filled', fontname = 'Source Sans Pro', fontsize = '12']
A [label = 'Elección de un monitor', fillcolor = '#C7645D']
B [label = 'Coste', fillcolor = '#E2807A']
C [label = 'Calidad de Imagen', fillcolor = '#E2807A']
D [label = 'Experiencia de Usuario', fillcolor = '#E2807A']
E [label = 'Precio', fillcolor = '#F8A29E']
F [label = 'Consumo', fillcolor = '#F8A29E']
G [label = 'Resolución', fillcolor = '#F8A29E']
H [label = 'Densidad', fillcolor = '#F8A29E']
I [label = 'Brillo', fillcolor = '#F8A29E']
J [label = 'Colores', fillcolor = '#F8A29E']
K [label = 'Tamaño', fillcolor = '#F8A29E']
L [label = 'Frecuencia', fillcolor = '#F8A29E']
edge[color = '#005A89', arrowsize = '0.5']
A -> {B C D}
B -> {E F}
C -> {G H I J}
D -> {K L}
}")Matrices de comparación por parejas
A continuación se establecen las siguientes matrices de comparación por parejas para los criterios, subcriterios y alternativas. Se ha realizado en un script anexo llamado “tablas_planteamiento_AHP.R” para una mejor legibilidad.
Nivel 1 - Criterios
En cuanto a los criterios, atendiendo a las indicaciones dadas por el arquitecto, se ha establecido la siquiente matriz de comparaciones dos a dos.
| Coste | Calidad de Imagen | Experiencia de Usuario | |
|---|---|---|---|
| Coste | 1 | 1/7 | 1/5 |
| Calidad de Imagen | 7 | 1 | 3 |
| Experiencia de Usuario | 5 | 1/3 | 1 |
Se ha valorado la calidad de imagen como de importancia muy fuerte sobre el precio y moderada sobre la experiencia de usuario, además de importancia fuerte de la experiencia de usuario sobre el precio. De esta forma relegamos el precio como criterio de menor importancia, lejos de la calidad de imagen (en primer lugar) y de la experiencia de usuario (segundo lugar).
Nivel 2 - Subcriterios:
Coste:
Los subcriterios dentro del coste eran precio y consumo, vemos su comparación dos a dos en esta tabla.
| Precio | Consumo | |
|---|---|---|
| Precio | 1 | 5 |
| Consumo | 1/5 | 1 |
Se considera que el precio es fuertemente más relevante que el consumo, pues el arquitecto tendría que pasar muchos años sin renovar este monitor para que el consumo tenga incidencia real en el coste del monitor.
Calidad de Imagen:
Los subcriterios que conforman la calidad de imagen son comparados dos a dos en la siguiente tabla.
| Resolución | Densidad | Brillo | Colores | |
|---|---|---|---|---|
| Resolución | 1 | 2 | 7 | 5 |
| Densidad | 1/2 | 1 | 5 | 3 |
| Brillo | 1/7 | 1/5 | 1 | 1/3 |
| Colores | 1/5 | 1/3 | 3 | 1 |
La resolución y la densidad son dos parámetros prácticamente de igual importancia, definen la calidad de un monitor conjuntamente, pero queremos que la resolución tenga una incidencia levemente superior en el resultado final. Por ello ambos subcriterios son más fuertes en relevancia que los otros dos, ajustándose los valores sobre los otros criterios a esta sutil diferencia entre resolución y densidad de píxeles. Por su parte, la cantidad de colores será algo más relevante que el brillo y le hemos dado una imporancia moderada sobre este.
Experiencia de Usuario:
La siguiente tabla muestra los subcriterios de la experiencia de usuario, tamaño y frecuencia de actualización.
| Tamaño | Frecuencia | |
|---|---|---|
| Tamaño | 1 | 3 |
| Frecuencia | 1/3 | 1 |
La importancia del tamaño sobre la frecuencia de actualización es moderada, el arquitecto pasa muchas horas delante del ordenador y la necesidad de una buena frecuencia, que ayude a un menor cansancio visual, es de casi la misma relevancia que un buen tamaño para el trabajo multitarea.
Nivel 3 - Alternativas:
A continuación, se comparan las alternativas para todos los subcriterios. Se añade un pequeño comentario acerca del criterio seguido.
Precio:
Se ha intentado dar la relevancia de los precios acorde a las diferencias de precio entre los monitores, de esta forma las alternativas más caras tienen relevancia casi idéntica entre si, la opción más económica oscila entre preferencias fuertes y extremas con el resto de monitores. Y las opciones intermedias oscilan entre preferencias moderadas y muy fuertes sobre las alternativas más caras.
| LG UltraFine 40WT95UF | Asus TUF Gaming VG27AQ3A | MSI MAG401QR | Asus VZ27EHF | Samsung UJ59 | |
|---|---|---|---|---|---|
| LG UltraFine 40WT95UF | 1 | 1/7 | 1/2 | 1/9 | 1/5 |
| Asus TUF Gaming VG27AQ3A | 7 | 1 | 5 | 1/4 | 3 |
| MSI MAG401QR | 2 | 1/5 | 1 | 1/7 | 1/4 |
| Asus VZ27EHF | 9 | 4 | 7 | 1 | 5 |
| Samsung UJ59 | 5 | 1/3 | 4 | 1/5 | 1 |
Consumo:
En cuanto al consumo, una opción destaca sobre las demás. Con 21W frente a 35W de la siguiente alternativa en menor consumo. Por ello su preferencia va desde muy fuerte hasta extrema sobre el resto de opciones. El resto de alternativas con consumos muy similares tienen preferencias entre muy moderadas y casi fuertes.
| LG UltraFine 40WT95UF | Asus TUF Gaming VG27AQ3A | MSI MAG401QR | Asus VZ27EHF | Samsung UJ59 | |
|---|---|---|---|---|---|
| LG UltraFine 40WT95UF | 1 | 1/4 | 1/2 | 1/9 | 1/3 |
| Asus TUF Gaming VG27AQ3A | 4 | 1 | 3 | 1/6 | 2 |
| MSI MAG401QR | 2 | 1/3 | 1 | 1/8 | 3 |
| Asus VZ27EHF | 9 | 6 | 8 | 1 | 7 |
| Samsung UJ59 | 3 | 1/2 | 1/3 | 1/7 | 1 |
Resolución:
En la resolución tenemos 3 grupos, y todas las preferencias son las mismas para las alternativas en cada grupo. Las de resolución más alta tienen preferencia extrema sobre la de resolución más baja y fuerte sobre las de resolución media. Mientras, las de resolución media tienen preferencia moderada sobre las de resolución baja.
| LG UltraFine 40WT95UF | Asus TUF Gaming VG27AQ3A | MSI MAG401QR | Asus VZ27EHF | Samsung UJ59 | |
|---|---|---|---|---|---|
| LG UltraFine 40WT95UF | 1 | 5 | 5 | 9 | 1 |
| Asus TUF Gaming VG27AQ3A | 1/5 | 1 | 1 | 3 | 1/5 |
| MSI MAG401QR | 1/5 | 1 | 1 | 3 | 1/5 |
| Asus VZ27EHF | 1/9 | 1/3 | 1/3 | 1 | 1/9 |
| Samsung UJ59 | 1 | 5 | 5 | 9 | 1 |
Densidad:
Para la densidad se ha intentado asignar la preferencia según los ppi de cada monitor, cuanto mayor es esta cifra sobre la de la alternativa a comparar, más fuerte será la preferencia sobre ella.
| LG UltraFine 40WT95UF | Asus TUF Gaming VG27AQ3A | MSI MAG401QR | Asus VZ27EHF | Samsung UJ59 | |
|---|---|---|---|---|---|
| LG UltraFine 40WT95UF | 1 | 3 | 5 | 7 | 1 |
| Asus TUF Gaming VG27AQ3A | 1/3 | 1 | 3 | 5 | 1/3 |
| MSI MAG401QR | 1/5 | 1/3 | 1 | 3 | 1/5 |
| Asus VZ27EHF | 1/7 | 1/5 | 1/3 | 1 | 1/7 |
| Samsung UJ59 | 1 | 3 | 5 | 7 | 1 |
Brillo:
Para el brillo se ha optado por un criterio similar al de la resolución.
| LG UltraFine 40WT95UF | Asus TUF Gaming VG27AQ3A | MSI MAG401QR | Asus VZ27EHF | Samsung UJ59 | |
|---|---|---|---|---|---|
| LG UltraFine 40WT95UF | 1 | 7 | 2 | 7 | 6 |
| Asus TUF Gaming VG27AQ3A | 1/7 | 1 | 1/3 | 1 | 2 |
| MSI MAG401QR | 1/2 | 6 | 1 | 6 | 5 |
| Asus VZ27EHF | 1/7 | 1 | 3 | 1 | 2 |
| Samsung UJ59 | 1/6 | 1/2 | 1/5 | 1/2 | 1 |
Colores:
En cuanto a la comparación dos a dos de la cantidad de colores (millones), se han hecho dos grupos. Los que tienen +1000 colores y los que tienen 16.7, así los del primer grupo tendrán una preferencia muy fuerte sobre los del segundo.
| LG UltraFine 40WT95UF | Asus TUF Gaming VG27AQ3A | MSI MAG401QR | Asus VZ27EHF | Samsung UJ59 | |
|---|---|---|---|---|---|
| LG UltraFine 40WT95UF | 1 | 7 | 1 | 7 | 1 |
| Asus TUF Gaming VG27AQ3A | 1/7 | 1 | 1/7 | 1 | 1/7 |
| MSI MAG401QR | 1 | 7 | 1 | 7 | 1 |
| Asus VZ27EHF | 1/7 | 1 | 1/7 | 1 | 1/7 |
| Samsung UJ59 | 1 | 7 | 1 | 7 | 1 |
Tamaño:
Criterio similar al de la resolución, pantallas en torno a las 40” preferencias muy fuertes sobre las de 27” y fuertes sobre la de 31.5”. Pantalla de 31.5” preferencia moderada sobre las de 27”.
| LG UltraFine 40WT95UF | Asus TUF Gaming VG27AQ3A | MSI MAG401QR | Asus VZ27EHF | Samsung UJ59 | |
|---|---|---|---|---|---|
| LG UltraFine 40WT95UF | 1 | 7 | 1 | 7 | 5 |
| Asus TUF Gaming VG27AQ3A | 1/7 | 1 | 1/7 | 1 | 1/3 |
| MSI MAG401QR | 1 | 7 | 1 | 7 | 5 |
| Asus VZ27EHF | 1/7 | 1 | 1/7 | 1 | 1/3 |
| Samsung UJ59 | 1/5 | 3 | 1/5 | 3 | 1 |
Frecuencia:
Criterio similar al del precio, dando la preferencia según el valor de la frecuencia de cada monitor.
| LG UltraFine 40WT95UF | Asus TUF Gaming VG27AQ3A | MSI MAG401QR | Asus VZ27EHF | Samsung UJ59 | |
|---|---|---|---|---|---|
| LG UltraFine 40WT95UF | 1 | 1/5 | 1/3 | 5 | 7 |
| Asus TUF Gaming VG27AQ3A | 5 | 1 | 3 | 7 | 9 |
| MSI MAG401QR | 3 | 1/3 | 1 | 6 | 8 |
| Asus VZ27EHF | 1/5 | 1/7 | 1/6 | 1 | 3 |
| Samsung UJ59 | 1/7 | 1/9 | 1/8 | 1/3 | 1 |
Desarrollo del problema
AHP con R
Introducción de las matrices en R
En primer lugar vamos a introducir las matrices de comparación por parejas para emplear las funciones de clase. Se ha utilizado además la función multicriterio.metodoAHP.chequeo.matrizcomparaciones para asegurar que las matrices son válidas.
## CRITERIOS
matriz_criterios_ahp <- multicriterio.crea.matrizvaloraciones_mej(
c(1/7,1/5,3), numalternativas = 3, v.nombres.alternativas = c(
"Coste", "Calidad de Imagen", "Experiencia de Usuario"))
## SUBCRITERIOS
#Coste
matriz_subcriterio_coste_ahp <- multicriterio.crea.matrizvaloraciones_mej(
c(5), numalternativas = 2, v.nombres.alternativas = c("Precio", "Consumo"))
#Calidad de imagen
matriz_subcriterio_calidad_ahp <- multicriterio.crea.matrizvaloraciones_mej(
c(2,7,5,5,3,1/3), numalternativas = 4, v.nombres.alternativas = c(
"Resolución", "Densidad", "Brillo", "Colores"))
#Experiencia de usuario
matriz_subcriterio_experiencia_ahp <- multicriterio.crea.matrizvaloraciones_mej(
c(3), numalternativas = 2, v.nombres.alternativas = c("Tamaño", "Frecuencia"))
## ALTERNATIVAS
#Precio
matriz_alternativas_precio_ahp <- multicriterio.crea.matrizvaloraciones_mej(
c(1/7,1/2,1/9,1/5,5,1/4,3,1/7,1/4,5), numalternativas = 5, v.nombres.alternativas = datos$Modelo)
#Consumo
matriz_alternativas_consumo_ahp <- multicriterio.crea.matrizvaloraciones_mej(
c(1/4,1/2,1/9,1/3,3,1/6,2,1/8,3,7), numalternativas = 5, v.nombres.alternativas = datos$Modelo)
#Resolución
matriz_alternativas_resolucion_ahp <- multicriterio.crea.matrizvaloraciones_mej(
c(5,5,9,1,1,3,1/5,3,1/5,1/9), numalternativas = 5, v.nombres.alternativas = datos$Modelo)
#Densidad
matriz_alternativas_densidad_ahp <- multicriterio.crea.matrizvaloraciones_mej(
c(3,5,7,1,3,5,1/3,3,1/5,1/7), numalternativas = 5, v.nombres.alternativas = datos$Modelo)
#Brillo
matriz_alternativas_brillo_ahp <- multicriterio.crea.matrizvaloraciones_mej(
c(7,2,7,6,1/3,1,2,6,5,2), numalternativas = 5, v.nombres.alternativas = datos$Modelo)
#Colores
matriz_alternativas_colores_ahp <- multicriterio.crea.matrizvaloraciones_mej(
c(7,1,7,1,1/7,1,1/7,7,1,1/7), numalternativas = 5, v.nombres.alternativas = datos$Modelo)
#Tamaño
matriz_alternativas_tamaño_ahp <- multicriterio.crea.matrizvaloraciones_mej(
c(7,1,7,5,1/7,1,1/3,7,5,1/3), numalternativas = 5, v.nombres.alternativas = datos$Modelo)
# Frecuencia
matriz_alternativas_frecuencia_ahp <- multicriterio.crea.matrizvaloraciones_mej(
c(1/5,1/3,5,7,3,7,9,6,8,3), numalternativas = 5, v.nombres.alternativas = datos$Modelo)## Intento trabajar con listas para reducir el código
lista_matrices_parejas <- list(matriz_criterios_ahp,
matriz_subcriterio_coste_ahp,
matriz_subcriterio_calidad_ahp,
matriz_subcriterio_experiencia_ahp,
matriz_alternativas_precio_ahp,
matriz_alternativas_consumo_ahp,
matriz_alternativas_resolucion_ahp,
matriz_alternativas_densidad_ahp,
matriz_alternativas_brillo_ahp,
matriz_alternativas_colores_ahp,
matriz_alternativas_tamaño_ahp,
matriz_alternativas_frecuencia_ahp)
## Le ponemos nombres para facilitar su localización
nombres_matrices <- c("Criterios", "Coste", "Calidad", "Experiencia",
"Precio", "Consumo", "Resolución", "Densidad",
"Brillo", "Colores", "Tamaño", "Frecuencia")
names(lista_matrices_parejas) <- nombres_matrices
## Ahora a todas las matrices de esta lista le aplicamos la función de inconsistencia
lista_inconsistencias <- lapply(lista_matrices_parejas, multicriterio.metodoAHP.coef.inconsistencia)
## Ahora a todas las matrices de la lista de matrices por parejas le aplicamos la función para calcular pesos
lista_pesos <- lapply(lista_matrices_parejas, multicriterio.metodoAHP.variante2.mediageometrica)Inconsistencia
Se ha realizado una tabla que recoge el análisis de inconsistencia de todas las matrices empleadas en el método AHP. Además se incluye una columna que recoge la validación de la matriz para su uso en el método AHP.
## Al usar el método con listas, la hemos calculado también para matrices 2x2 sin ser necesario.
# Esta función, permite redondear RI de aquellos que queremos calcular y sustituye NaN por "-"
# para mostrarlo en la tabla.
convertir_vector_valores_listaNaN <- function (x) {
if(is.nan(x$RI.coef.inconsistencia)){
inter <- "-"
} else {
inter <- round(x$RI.coef.inconsistencia,4)
}
return(inter)
}
tabla_inconsistencia_ahp <- data.frame(
Matriz = c(
"Criterios",
"Subcriterio Coste",
"Subcriterio Calidad de Imagen",
"Subcriterio Experiencia de Usuario",
"Alternativa Precio",
"Alternativa Consumo",
"Alternativa Resolución",
"Alternativa Densidad",
"Alternativa Brillo",
"Alternativa Colores",
"Alternativa Tamaño",
"Alternativa Frecuencia"
),
`RI Coeficiente inconsistencia` = sapply(lista_inconsistencias, convertir_vector_valores_listaNaN),
Estado = sapply(lista_inconsistencias, function(x) x$mensaje),
`Matriz aceptable` = sapply(lista_matrices_parejas, multicriterio.metodoAHP.chequeo.matrizcomparaciones))
crea_tabla_estilo(tabla_inconsistencia_ahp, nombresfila = FALSE)| Matriz | RI.Coeficiente.inconsistencia | Estado | Matriz.aceptable |
|---|---|---|---|
| Criterios | 0.0559 | Consistencia aceptable | TRUE |
| Subcriterio Coste | Consistencia aceptable | TRUE | |
| Subcriterio Calidad de Imagen | 0.0254 | Consistencia aceptable | TRUE |
| Subcriterio Experiencia de Usuario | Consistencia aceptable | TRUE | |
| Alternativa Precio | 0.0658 | Consistencia aceptable | TRUE |
| Alternativa Consumo | 0.0869 | Consistencia aceptable | TRUE |
| Alternativa Resolución | 0.0094 | Consistencia aceptable | TRUE |
| Alternativa Densidad | 0.0304 | Consistencia aceptable | TRUE |
| Alternativa Brillo | 0.0298 | Consistencia aceptable | TRUE |
| Alternativa Colores | 0 | Consistencia aceptable | TRUE |
| Alternativa Tamaño | 0.021 | Consistencia aceptable | TRUE |
| Alternativa Frecuencia | 0.0859 | Consistencia aceptable | TRUE |
Si alguna de las matrices de comparación hubiese dado un coeficiente de inconsistencia mayor a 0.1, tendríamos que haber revisado la matriz en cuestión para asegurarnos de que las relaciones lógicas entre las alternativas se han respetado. En nuestro caso, su realización ha sido meticulosa y la consistencia se ha podido cumplir sin rehacer las tablas.
Cálculo de los pesos
Criterios:
En primer lugar vamos a calcular los pesos finales para el último nivel de criterios y subcriterios, para ello multiplicaremos la valoración de cada criterio por la valoración de cada uno de los subcriterios que lo componen.
# Preparación matriz criterios*subcriterios
c11 <- lista_pesos$Criterios$valoraciones.ahp[1] * lista_pesos$Coste$valoraciones.ahp[1]
c12 <- lista_pesos$Criterios$valoraciones.ahp[1] * lista_pesos$Coste$valoraciones.ahp[2]
c21 <- lista_pesos$Criterios$valoraciones.ahp[2] * lista_pesos$Calidad$valoraciones.ahp[1]
c22 <- lista_pesos$Criterios$valoraciones.ahp[2] * lista_pesos$Calidad$valoraciones.ahp[2]
c23 <- lista_pesos$Criterios$valoraciones.ahp[2] * lista_pesos$Calidad$valoraciones.ahp[3]
c24 <- lista_pesos$Criterios$valoraciones.ahp[2] * lista_pesos$Calidad$valoraciones.ahp[4]
c31 <- lista_pesos$Criterios$valoraciones.ahp[3] * lista_pesos$Experiencia$valoraciones.ahp[1]
c32 <- lista_pesos$Criterios$valoraciones.ahp[3] * lista_pesos$Experiencia$valoraciones.ahp[2]
criterios_subcriterios <- c(c11,c12,c21,c22,c23,c24,c31,c32)
names(criterios_subcriterios) <- nombres_matrices[5:12]Los podemos ver en la siguiente tabla.
tabla_criterios_subcriterios <- crea_tabla_estilo(data.frame(
Criterios = names(criterios_subcriterios),
Peso = criterios_subcriterios
), nombresfila = FALSE)
tabla_criterios_subcriterios| Criterios | Peso |
|---|---|
| Precio | 0.05993952 |
| Consumo | 0.01198790 |
| Resolución | 0.33961705 |
| Densidad | 0.19430335 |
| Brillo | 0.03667901 |
| Colores | 0.07851859 |
| Tamaño | 0.20921592 |
| Frecuencia | 0.06973864 |
Alternativas:
Vamos ahora a calcular los pesos finales para cada alternativa, donde un mayor peso indicará preferencia sobre alternativas con menor ponderación final.
mat_pesos_alternativas <- matrix(c(
sapply(lista_pesos[5:12],function(x) x$valoraciones.ahp)
),
ncol = 5, nrow = 8, byrow = TRUE)
ponderaciones_final <- data.frame((criterios_subcriterios %*% mat_pesos_alternativas))
colnames(ponderaciones_final) <- datos$ModeloTambién los mostramos en una tabla:
tabla_ponderación_final <- crea_tabla_estilo(ponderaciones_final, nombresfila = FALSE)
tabla_ponderación_final| LG UltraFine 40WT95UF | Asus TUF Gaming VG27AQ3A | MSI MAG401QR | Asus VZ27EHF | Samsung UJ59 |
|---|---|---|---|---|
| 0.3428178 | 0.1285062 | 0.1855899 | 0.07897614 | 0.2641099 |
AHP con paquete
Preparación del modelo
En primer lugar tenemos que crear el archivo ahp que almacena el modelo necesario para este paquete, se encuentra en la raíz del proyecto y lo cargamos con ayuda del paquete ahp. Además vamos a calcular las prioridades, pero no vamos a mostrar el modelo en el documento.
modelo_ahp <- ahp::Load("modelo_monitores.ahp")
#Paso 2. Calcular las prioridades
Calculate(modelo_ahp)
# print(modelo_ahp, priority = function(x) x$parent$priority["Total", x$name])Jerarquía de los criterios
Para observar que el modelo se ha introducido correctamente, y para una mejor comprensión nos vamos a apoyar del siguiente grafo, que nos permite observar la jerarquía de los criterios, los subcriterios y las alternativas.
#Paso 3. Visualizar la jerarquía
Visualize(modelo_ahp,
criteriaNodesStyle = list(
style = "filled, rounded",
penwidth = 3,
color = "#C3625B",
fillcolor = "#F8A29E" ,
shape = "box",
fontname = "sans-serif"),
alternativeNodesStyle = list(
style = "filled, rounded",
penwidth = 3,
color = "#005682",
fillcolor = "#7FBFF5" ,
shape = "box",
fontname = "sans-serif"))Análisis
En este último paso vamos a análizar el modelo, para ello vamos a mostrar en dos tablas los resultados para este modelo. También hay una opción en el paquete para mostrar este resultado sin tabla, se ha escogido la opción con tabla por facilitar su lectura e interpretación. Así no mostramos resultados repetidos.
# Tabla "priority"
aa = AnalyzeTable(modelo_ahp,variable = "priority",sort = "orig", weightColor = "#F8A29E", consistencyColor = "#C6AA74", alternativeColor = "#7FBFF5")
formattable::as.htmlwidget(aa)Esta primera tabla muestra en cada fila de los subcriterios el peso que tiene cada alternativa en ese subcriterio, facilita ver con claridad que alternativa se desempeña mejor en cada subcriterio. En la columna “Priority” podemos ver el desglose de los pesos, primero como se reparte la prioridad total entre cada criterio (Coste un 7’2%, Calidad un 64’9% y Experiencia de usuario un 27’9%) y segundo el mismo reparto en cada subcriterio. Es decir, nos muestra el porcentaje de prioridad dentro de cada grupo. Además del cálculo de la inconsistencia en la última columna.
#Tabla pesos
aa = AnalyzeTable(modelo_ahp, sort = "orig", weightColor = "#F8A29E", consistencyColor = "#C6AA74", alternativeColor = "#7FBFF5")
formattable::as.htmlwidget(aa)En esta otra se ven los pesos para cada monitor (ponderaciones finales) en la primera fila, además la fila de cada criterio muestra cuanto del peso total viene dado por este criterio para cada alternativa, de forma que la suma de los porcentajes de cada alternativa en esos criterios es el peso asignado a cada alternativa, y de igual forma para los subcriterios. Así para la alternativa elegida: Peso a1 = 34,2%, Coste (0,3%) + Calidad (24,6%) + Experiencia (9,3%), análogo para los subcriterios, nos permite observar cuanto ha influido cada criterio/subcriterio para el peso final de las alternativas. Esta tabla contiene los resultados que hemos obtenido con las funciones de clase la ya mencionada primera fila y en la columna “Weight” si nos fijamos en las filas de los subcriterios, encontramos los pesos que hemos obtenido para el último nivel de la jerarquía de criterios.
Uso de la aplicación shiny
ahp::RunGUI()Se adjuntan algunas capturas que se han realizado mientras se utilizaba la aplicación shiny para este problema. Los resultados son iguales a los obtenidos en el código aquí expuesto.
Conclusiones AHP
Podemos decir que obtenemos dos conclusiones principales tras el análisis de este problema multicriterio con AHP. Ambos métodos usados (funciones de clase y paquete ahp) deben ofrecer, y ofrecen, los mismos resultados.
La primera es relativa a los pesos que se han asignado a los criterios con los que empezábamos el problema (tras utilizar la jerarquía por niveles). Estos pesos serán válidos para otros métodos de decisión multicriterio y consideramos el método AHP como consistente a la hora de obtener pesos (también) para otros métodos.
La segunda es relativa a las ponderaciones finales de cada una de las alternativas, y esto se traduce en que la mejor alternativa es el modelo “LG Ultrafine 40WT95UF” con un peso del 34’28%. La que será nuestra decisión final. Además la segunda alternativa preferida sería el modelo “Samsung UJ59” con un peso del 26’41%. Esta información la emplearemos para comparar los métodos posteriormente.
Planteamiento para el método ELECTRE
Matriz de decisión
Se establece la matriz de decisión, tenemos que hacer negativos los valores que se van a minimizar. Esta matriz de decisión será empleada en los métodos posteriores.
matriz_decisión <- multicriterio.crea.matrizdecision(
c(-505,-40,2160,139,450,1060,39.7,120,
-244,-35,1440,108,250,16.7,27,180,
-449,-39,1440,93,400,1070,40,155,
-108,-21,1080,81,250,16.7,27,100,
-290,-37,2160,139,270,1000,31.5,60
),
numalternativas = 5,
numcriterios = 8,
v.nombresalt = names(ponderaciones_final),
v.nombrescri = names(criterios_subcriterios)
)
matriz_decisión Precio Consumo Resolución Densidad Brillo Colores
LG UltraFine 40WT95UF -505 -40 2160 139 450 1060.0
Asus TUF Gaming VG27AQ3A -244 -35 1440 108 250 16.7
MSI MAG401QR -449 -39 1440 93 400 1070.0
Asus VZ27EHF -108 -21 1080 81 250 16.7
Samsung UJ59 -290 -37 2160 139 270 1000.0
Tamaño Frecuencia
LG UltraFine 40WT95UF 39.7 120
Asus TUF Gaming VG27AQ3A 27.0 180
MSI MAG401QR 40.0 155
Asus VZ27EHF 27.0 100
Samsung UJ59 31.5 60
Parámetros para el método
Pesos
Como se ha mencionado anteriormente, vamos a emplear los pesos que hemos obtenido tras emplear el método AHP para los criterios y subcriterios.
| Criterios | Peso |
|---|---|
| Precio | 0.05993952 |
| Consumo | 0.01198790 |
| Resolución | 0.33961705 |
| Densidad | 0.19430335 |
| Brillo | 0.03667901 |
| Colores | 0.07851859 |
| Tamaño | 0.20921592 |
| Frecuencia | 0.06973864 |
Test de concordancia
El test de concordancia requiere un valor alfa que al ser reducido permite que más alternativas dominen a otras. El valor de alfa inicial que vamos a tomar es 0.7.
Test de discordancia
Los valores para \(d_i\) pueden condicionar el resultado, en nuestro caso tenemos pocas alternativas, de características y rangos de precio muy variadas. Que lo hacen muy sensible a estos valores.
- Brillo: Una diferencia mayor de 50 nits en el brillo será suficiente para no pasar el test de discordancia.
- Colores: Se considera que diferencias menores a 100 (millones de colores) son insuficientes para no pasar el test de discordancia.
- Tamaño de pantalla: Una diferencia mayor de 3” hará que no se supere el test de discordancia
A continuación se proponen otros posibles valores para ejemplos con mayor cantidad de alternativas o con modelos de una gama similar.
- Precio: 150€
- Consumo: 15W
- Resolución: 720 px
- Densidad de píxeles: 40 ppi
- Frecuencia de refresco: 60 Hz
Además se considera que estas cantidades deberían ser ajustadas e introducidas en el método acorde a los pesos y las magnitudes. Por ejemplo, si se hubiera dado mayor importancia al precio en los pesos podríamos introducirlo como elemento para no superar el test de discordancia.
Algunas de las cantidades propuestas, como la resolución, serían adecuadas para este problema. La no influencia en el resultado final ha desincentivado su inclusión.
Desarrollo del método ELECTRE
Primera iteración
iteración1_ELECTRE <- multicriterio.metodoELECTRE_I(matriz_decisión,
pesos.criterios = criterios_subcriterios,
nivel.concordancia.minimo.alpha = 0.7,
no.se.compensan = c(Inf,Inf,Inf,Inf,50,100,3,Inf),
que.alternativas = TRUE
)
alternativas_iteración1_ELECTRE <- iteración1_ELECTRE$nucleo_aprox
tabla_alternativas_nombre <- data.frame(`Alternativa número` = c(1:5),
Modelo = names(ponderaciones_final))
construir_grafo_animado(iteración1_ELECTRE$relacion.dominante, plantilla = "spring")resultados_iteración1_ELECTRE <- func_ELECTRE_Completo(iteración1_ELECTRE)Vemos que para este valor de alfa, las mejores alternativas son 1, 3. Observando el grafo, vemos que son las únicas alternativas que no son dominadas por otras, además podríamos concluir que la siguiente mejor opción es a5.
Vamos a reducir el valor de alfa y nos vamos a quedar con estas dos alternativas para la segunda iteración.
iteración2_ELECTRE <- multicriterio.metodoELECTRE_I(matriz_decisión,
pesos.criterios = criterios_subcriterios,
nivel.concordancia.minimo.alpha = 0.6,
no.se.compensan = c(Inf,Inf,Inf,Inf,50,100,3,Inf),
que.alternativas = c(1,3)
)
alternativas_iteración2_ELECTRE <- iteración2_ELECTRE$nucleo_aprox
construir_grafo(iteración2_ELECTRE$relacion.dominante, que.alternativas = c(1,3))Se puede observar que para \(\alpha\) = 0.6 no hay dominancia de ninguna de estas alternativas sobre la otra. Vamos a reducir su valor una vez más y volvemos a aplicar el método.
iteración3_ELECTRE <- multicriterio.metodoELECTRE_I(matriz_decisión,
pesos.criterios = criterios_subcriterios,
nivel.concordancia.minimo.alpha = 0.55,
no.se.compensan = c(Inf,Inf,Inf,Inf,50,100,3,Inf),
que.alternativas = c(1,3)
)
alternativas_iteración3_ELECTRE <- iteración3_ELECTRE$nucleo_aprox
construir_grafo(iteración3_ELECTRE$relacion.dominante, que.alternativas = c(1,3))Con este valor de \(\alpha\) podemos ver que la alternativa LG UltraFine 40WT95UF domina a la alternavita MSI MAG401QR.
Conclusiones del método ELECTRE
Hemos observado que la mejor alternativa es a1, siendo la segunda mejor alternativa a3. Este método es menos flexible….
Pesos
Vamos a emplear los pesos calculados en AHP para el último nivel de la jerarquía de criterios y subcriterios.
| Criterios | Peso |
|---|---|
| Precio | 0.05993952 |
| Consumo | 0.01198790 |
| Resolución | 0.33961705 |
| Densidad | 0.19430335 |
| Brillo | 0.03667901 |
| Colores | 0.07851859 |
| Tamaño | 0.20921592 |
| Frecuencia | 0.06973864 |
Funciones de preferencia
Para cada criterio vamos a elegir una función de preferencia según la naturaleza de cada uno, tratando además que proporcionen mayor satisfacción a los requisitos del arquitecto. Recordemos los criterios:
Precio: El precio no está entre los requisitos más importantes, pero queremos que tenga algo de indicencia en la decisión final, querríamos que para cantidades con diferencias pequeñas no exista preferencia alguna. Por ello vamos a tomar un valor de Q= 50€
Consumo: El coste anual que supone una diferencia de 10W trabajando es de 2.4€; Cálculo: 10W = 0.01 kW, 6 horas al día todos los días, 0.01 kW x 6 x 365 = 21.90 kWh anuales. Con el precio medio actual 0.1090 €/kWh: 21.90 kWh x 0.1090 €/kWh = 2.3871€. Esto motiva que optemos por el Cuasi-Criterio. Con no preferencia en todas las diferencias menores que Q = 10W.
Resolución: Aquí queremos que haya dominancia absoluta en aquellos valores que superen a otros por 720 px, de esta forma establecemos niveles bien diferenciados según la resolución. Preferencia lineal
Densidad: Para la densidad de píxeles vamos a emplear el criterio usual, queremos que cualquier diferencia positiva resulte en preferencia absoluta. Si tuviéramos monitores con densidad de píxeles por encima de 150 elegiríamos un criterio que nos permitiera diferenciar que a partir de esa cantidad apenas existe diferencia.
Brillo: Para el brillo vamos a optar por dar preferencia a monitores con más de 100 nits de diferencia. Preferencia lineal.
Colores: En el caso de los colores vamos a tratar de diferenciar aquellos con 16.7 millones de colores de aquellos que tienen +1000 millones de colores. Así cuando la diferencia sea menor de 100 (M) diremos que no hay preferencia. Cuasi-criterio.
Tamaño: En cuanto al tamaño, queremos que monitores de tamaños muy similares no tengan dominancia entre si y que cualquier salto de tamaño medio nos proporcione dominancia absoluta. Para ello P = 4” y Q = 2”. Función elegida lineal con área de indiferencia.
Frecuencia: La frecuencia de refresco sigue una escala particular, normalmente saltos de 30 Hz se hacen notar bastante hasta cierta cantidad de Hz que los saltos deben ser mayores para que se note. Como para el arquitecto es un factor secundario, vamos a tomar que diferencias menores a 20 Hz no supondrán preferencia de una alternativa sobre otra y que saltos de 59 Hz si harán que escojamos una alternativa con preferencia absoluta. Para los valores intermedios queremos un reparto suavizado, vamos a tomar S = 60 Hz
Creamos la matriz de preferencia con estos valores.
tabla_preferencia <- matrix(c(2,50,0,0,
2,10,0,0,
3,0,720,0,
1,0,0,0,
3,0,100,0,
2,100,0,0,
5,2,4,0,
6,60,20,60),
ncol = 4,
byrow = TRUE)PROMETHEE I
resultado_Promethee_I <- multicriterio.metodo.promethee_i(matriz_decisión,
criterios_subcriterios,
tabla_preferencia)
resultado_Promethee_I$tabla.indices LG UltraFine 40WT95UF Asus TUF Gaming VG27AQ3A
LG UltraFine 40WT95UF 0.00000000 0.85833393
Asus TUF Gaming VG27AQ3A 0.08737954 0.00000000
MSI MAG401QR 0.07085030 0.32441353
Asus VZ27EHF 0.07192743 0.07192743
Samsung UJ59 0.05993952 0.82899072
MSI MAG401QR Asus VZ27EHF Samsung UJ59
LG UltraFine 40WT95UF 0.55225991 0.8621026 0.27333496
Asus TUF Gaming VG27AQ3A 0.26004127 0.4051801 0.06030054
MSI MAG401QR 0.00000000 0.7124489 0.29572238
Asus VZ27EHF 0.07192743 0.0000000 0.08582373
Samsung UJ59 0.59385993 0.8289907 0.00000000
resultado_Promethee_I$tablarelacionsupera LG UltraFine 40WT95UF Asus TUF Gaming VG27AQ3A
LG UltraFine 40WT95UF 0.5 1.0
Asus TUF Gaming VG27AQ3A 0.0 0.5
MSI MAG401QR 0.0 1.0
Asus VZ27EHF 0.0 0.0
Samsung UJ59 0.0 1.0
MSI MAG401QR Asus VZ27EHF Samsung UJ59
LG UltraFine 40WT95UF 1.0 1.0 1.0
Asus TUF Gaming VG27AQ3A 0.0 1.0 0.0
MSI MAG401QR 0.5 1.0 0.0
Asus VZ27EHF 0.0 0.5 0.0
Samsung UJ59 1.0 1.0 0.5
qgraph::qgraph(resultado_Promethee_I$tablarelacionsupera, color = "#F8A29E", edge.color = "#005682" , edge.width = 0.5)construir_grafo_animado(resultado_Promethee_I$tablarelacionsupera, plantilla = "circle")Medias
resultado_Promethee_I_medias <- multicriterio.metodo.promethee_i_med(matriz_decisión, criterios_subcriterios, tabla_preferencia)
qgraph::qgraph(resultado_Promethee_I_medias$tablarelacionsupera)PROMETHEE II
resultado_Promethee_II <- multicriterio.metodo.promethee_ii(matriz_decisión, criterios_subcriterios, tabla_preferencia)
resultado_Promethee_II$vflujos.netos LG UltraFine 40WT95UF Asus TUF Gaming VG27AQ3A MSI MAG401QR
2.25593464 -1.27076414 -0.07465348
Asus VZ27EHF Samsung UJ59
-2.50711630 1.59659928
qgraph::qgraph(resultado_Promethee_II$tablarelacionsupera)resultado_Promethee_II_Win <- multicriterio.metodo.promethee_windows(matriz_decisión, tabla_preferencia, criterios_subcriterios, c(rep("min",2),rep("max",6)))
source("teoriadecision_funciones_multicriterio_utiles.R")
test <- multicriterio.metodo.promethee_windows_kableExtra_html(resultado_Promethee_II_Win)
test$tabEscenario| Criterio1 | Criterio2 | Criterio3 | Criterio4 | Criterio5 | Criterio6 | Criterio7 | Criterio8 | |
|---|---|---|---|---|---|---|---|---|
| Preferencias | ||||||||
| Min/Max | min | min | max | max | max | max | max | max |
| Pesos | 0.0599395249018804 | 0.0119879049803761 | 0.339617051476852 | 0.194303352071175 | 0.0366790139892087 | 0.0785185870940899 | 0.209215924114814 | 0.0697386413716046 |
| Funciones Preferencias | U-shape (2) | U-shape (2) | V-shape (3) | Usual (1) | V-shape (3) | U-shape (2) | Linear (5) | Gaussian (6) |
| Q: Indiferencia | 50 | 10 | 0 | 0 | 0 | 100 | 2 | 60 |
| P: Preferencia | 0 | 0 | 720 | 0 | 100 | 0 | 4 | 20 |
| S: Gausiano | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 60 |
| Estadísticas | ||||||||
| Minimo | 108 | 21 | 1080 | 81 | 250 | 16.7 | 27 | 60 |
| Maximo | 505 | 40 | 2160 | 139 | 450 | 1070 | 40 | 180 |
| Media | 319.2 | 34.4 | 1656 | 112 | 324 | 632.68 | 33.04 | 123 |
| Desviacion Tipica | 143.17 | 6.92 | 432 | 23.65 | 84.29 | 503.52 | 5.8 | 41.9 |
| Evaluaciones | ||||||||
| LG UltraFine 40WT95UF | 505 | 40 | 2160 | 139 | 450 | 1060 | 39.7 | 120 |
| Asus TUF Gaming VG27AQ3A | 244 | 35 | 1440 | 108 | 250 | 16.7 | 27 | 180 |
| MSI MAG401QR | 449 | 39 | 1440 | 93 | 400 | 1070 | 40 | 155 |
| Asus VZ27EHF | 108 | 21 | 1080 | 81 | 250 | 16.7 | 27 | 100 |
| Samsung UJ59 | 290 | 37 | 2160 | 139 | 270 | 1000 | 31.5 | 60 |
test$tabAcciones| Rango | Phi | Phi.mas | Phi.menos | |
|---|---|---|---|---|
| LG UltraFine 40WT95UF | 1 | 0.5640 | 0.6365 | 0.0725 |
| Samsung UJ59 | 2 | 0.3991 | 0.5779 | 0.1788 |
| MSI MAG401QR | 3 | -0.0187 | 0.3509 | 0.3695 |
| Asus TUF Gaming VG27AQ3A | 4 | -0.3177 | 0.2032 | 0.5209 |
| Asus VZ27EHF | 5 | -0.6268 | 0.0754 | 0.7022 |
intalpha <- seq(1,2,0.1)
sols <- vector("list",length(intalpha))
sols_pasos <- vector("list",length(intalpha))
for (i in 1:length(intalpha)) {
Mat_i <- matriz_decisión
Mat_i[1,] <- Mat_i[1,] * intalpha[i]
sol_ArrowRaymond_i <- multicriterio.metodoaxiomatico.ArrowRaymond(Mat_i)
sols[[i]] <- sol_ArrowRaymond_i$alternativasordenadas
sols_pasos[[i]] <- sol_ArrowRaymond_i$pasos
}
sols_pasos[[1]][[4]]$Mclasificacion LG UltraFine 40WT95UF MSI MAG401QR
LG UltraFine 40WT95UF NA 3
MSI MAG401QR 5 NA
Posiciones de las alternativas a lo largo del vector alfas
observar_posiciones <- function(valfas, alter, solu){
posiciones = rep(NA,length(valfas))
for (i in 1:length(valfas)) {
#i = 1
posiciones[i] = which(solu[[i]]==alter)
}
return(posiciones)
}
lista_ArrowRaymond <- lapply(names(ponderaciones_final), observar_posiciones, valfas=intalpha, solu=sols)dataframe_ArrowRaymon <- lista_ArrowRaymond |>
purrr::imap_dfr(~ tibble(
alpha = intalpha,
posicion = .x,
alternativa = paste0("a", .y)
))
ggplot(dataframe_ArrowRaymon, aes(x = alpha, y = posicion, color = alternativa)) +
geom_line(linewidth = 1.2) +
geom_point(size = 2) +
scale_color_manual(values = c("#005682", "#C3625B", "#2E8B57", "#E19C29", "#7B68EE")) +
labs(
title = "Evolución de posiciones por alternativa",
x = expression(alpha),
y = "Posición"
) +
theme_minimal(base_size = 14) +
theme(
legend.title = element_blank(),
legend.position = "top",
plot.title = element_text(face = "bold", hjust = 0.5),
panel.grid.minor = element_blank()
)